#include "eventloop/IOchannel.h"
#include "net/TCPClient.h"
#include "log/Logger.h"
#include "eventloop/Eventloop.h"
#include "net/Sockaddr.h"
#include "utility/chrono.h"
#include "net/TCPConnection.h"
#include "thread/current_thread.h"

#include <functional>
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <cstring>

class TestClient
{
 public:
  TestClient(Eventloop* loop, const Sockaddr& listenAddr)
    : loop_(loop),
      _client(*loop, listenAddr, std::string("TestClient")),
      stdinChannel_(*loop, 0)
  {
    using namespace std::placeholders;
    _client.set_connection_callback( 
        std::bind(&TestClient::onConnection, this, _1));
    _client.set_message_callback(
        std::bind(&TestClient::onMessage, this, _1, _2, _3));
    //_client.enableRetry();
    // 标准输入缓冲区中有数据的时候，回调TestClient::handleRead
    stdinChannel_.set_read_callback(std::bind(&TestClient::handleRead, this));
	  stdinChannel_.enable_reading();		// 关注可读事件
  }

  void  connect()
  {
    _client.connect();
  }

 private:
  void onConnection(const TCPConnectionPtr& conn)
  {
    if (conn->is_connected())
    {
      printf("onConnection(): new connection [%s] from %s\n",
             conn->name().c_str(),
             conn->peer().IP_port().c_str());
    }
    else
    {
      printf("onConnection(): connection [%s] is down\n",
             conn->name().c_str());
    }
  }

  void onMessage(const TCPConnectionPtr& conn, Buffer &buf, Utility::timepoint time)
  {
    std::string msg(buf.retrieve_as_string());
    printf("onMessage(): recv a message [%s]\n", msg.c_str());
    LOG_INFO << conn->name() << " recv " << msg.size() << " bytes at " << Utility::to_string(time);
  }

  // 标准输入缓冲区中有数据的时候，回调该函数
  void handleRead()
  {
    char buf[1024] = {0};
    fgets(buf, 1024, stdin);
	  buf[strlen(buf)-1] = '\0';		// 去除\n
	  _client.connection()->send(buf);
  }

  Eventloop* loop_;
  TCPClient _client;
  IOchannel stdinChannel_;		// 标准输入Channel
};

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << ::getpid() << ", tid = " << CurrentThread::tid();
  Eventloop loop;
  Sockaddr serverAddr("127.0.0.1", 8888);
  TestClient client(&loop, serverAddr);
  client.connect();
  loop.loop();
}

